# build in python3.5
# author : hashaki
from vnpy.api.okex.OkcoinFutureAPI import OKexFutureByCCH
from threading import Thread
import time
import traceback
import sys
import json
import hashlib
from vnpy.api.okex.okexData import FUTURES_ERROR_DICT
from vnpy.trader.Rest import restshop
 # 合约持仓查询地址
OKEX_CONTRACT_HOST = 'https://www.okex.com/api/v1/future_hold_amount.do?symbol=%s_usd&contract_type=%s'

CONTRACT_SYMBOL = ["btc","ltc","eth","etc","bch","eos","xrp","btg"]

KLINE_PERIOD = ["1min","3min","5min","15min","30min","1hour","2hour","4hour","6hour","12hour","day","3day","week"]

CONTRACT_TYPE = ["this_week", "next_week", "quarter"]

class RESTFutureAPI(OKexFutureByCCH):
    def __init__(self):
        self.apiKey=''
        self.secretKay=''
        super(RESTFutureAPI,self).__init__(self.apiKey,self.secretKay)
        self.active=False               # 开关
        self.use_lever_rate = 10         # 杠杆
        self.trace = False

    #---------------------------------------------------------------
    def connct(self,apiKey,secretKey,trace=False):
        '''连接'''
        #self.host = ''                       # 调底层API即可
        self.apiKey = apiKey
        self.secretKey = secretKey
        self.trace = trace
        self.rest=restshop()
        # 这里应该调用REST API返回账户信息
        try:
            print(self.exchange_rate())
            self.thread=Thread(target=self.rest_run_forever,args=())
            self.thread.start()
        except Exception as error:
            print("连接失败：",error)

    #-----------------------------------------------------------------
    def rest_run_forever(self):
        '''一直运行'''
        while self.active:
            print("这里应该放一个抽象的执行方法--cchokex.py--rest_run_forever()")   # 执行方法应该为行情查询相关的
            time.sleep(1)

    #------------------------------------------------------------------
    def http_get_request(self, url, params, add_to_headers=None, TIMEOUT=5):
        import requests
        headers = {
            "Content-type": "application/x-www-form-urlencoded",
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0'
        }
        if add_to_headers:
            headers.update(add_to_headers)
        #postdata = urllib.urlencode(params)
        try:
            # response = requests.get(url, postdata, headers=headers, timeout=TIMEOUT)
            response = requests.get(url, headers=headers, timeout=TIMEOUT)
            if response.status_code == 200:
                return response.json()
            else:
                return {"status": "fail"}
        except Exception as e:
            print(u'httpGet failed :{}'.format(str(e)), file=sys.stderr)
            return {"status": "fail", "msg": e}

    # ----------------------------------------------------------------------
    def getContractName(self, symbol_no_usd, contract_type):
        try:
            url = OKEX_CONTRACT_HOST % (symbol_no_usd, contract_type)
            data = self.http_get_request(url, {})

            if type(data) == type([]) and len(data) > 0:
                d1 = data[0]
                contract_name = d1["contract_name"]
                return contract_name

        except Exception as ex:
            print(u'CCHOKEX.getContractName exception:{},{}'.format(str(ex),traceback.format_exc()), file=sys.stderr)
            return None

    def sendHeartBeat(self):          # REST没有心跳
        """
        发送心跳
        :return:
        """
        print("心跳功能被调用了--cchokex.py--sendHeartBeat()")
        
    # ----------------------------------------------------------------------
    def close(self):
        """关闭接口"""
        if self.thread and self.thread.isAlive():
            self.active=False                               # 原self.ws.close()
            self.thread.join()

    # ----------------------------------------------------------------------
    def readData(self, evt):
        """解压缩推送收到的数据,如果需要，这里作为数据处理"""
        data = json.loads(evt)
        return data

    # ----------------------------------------------------------------------
    def onMessage(self, rest, evt):
        """信息推送"""
        print(evt)

    # ----------------------------------------------------------------------
    def onError(self, rest, evt):
        """错误推送"""
        print('CCHOKEX.onError:{}'.format(evt))

    # ----------------------------------------------------------------------
    def onClose(self, rest):
        """接口断开"""
        print('CCHOKEX.onClose')

    # ----------------------------------------------------------------------
    def onOpen(self, rest):
        """接口打开"""
        print('CCHOKEX.onOpen')

    def subsribeFutureTicker(self, symbol, contractType):
        req = {'channel':'OKEX_FUTURE_TICKER','symbol':symbol,'contractType':contractType}
        self.rest.send(req)

    def subscribeFutureKline(self, symbol, contractType, timeType):
        req = {'channel':'OKEX_FUTURE_KLINE','symbol':symbol,'contractType':contractType,'timeType':timeType
        }
        self.rest.send(req)

    def subscribeFutureDepth(self, symbol, contractType):
        req = {'channel':'OKEX_FUTURE_DEPTH','symbol':symbol,'contractType':contractType,'size':'10'}
        self.rest.send(req)

    def subscribeFutureDepth20(self, symbol, contractType):
        req = {'channel':'OKEX_FUTURE_DEPTH','symbol':symbol,'contractType':contractType,'size':'20'}
        self.rest.send(req)

    def subscribeFutureTrades(self, symbol, contractType):
        req = {'channel':'OKEX_FUTURE_TRADES','symbol':symbol,'contractType':contractType}
        self.rest.send(req)

    def subscribeFutureIndex(self, symbol):
        req = {'channel':'OKEX_FUTURE_INDEX','symbol':symbol}
        self.rest.send(req)

    # ----------------------------------------------------------------------
    def generateSign(self, params):
        """生成签名"""
        l = []
        for key in sorted(params.keys()):
            l.append('%s=%s' % (key, params[key]))
        l.append('secret_key=%s' % self.secretKey)
        sign = '&'.join(l)
        return hashlib.md5(sign.encode('utf-8')).hexdigest().upper()

    # ----------------------------------------------------------------------
    #                       需要修改的核心方法
    #-----------------------------------------------------------------------
    def sendTradingRequest(self, channel, params):
        """发送交易请求"""
        # 在参数字典中加上api_key和签名字段
        params['apikey'] = self.apiKey
        params['sign'] = self.generateSign(params)

        # 生成请求
        d = {}
        d['channel'] = channel
        d['apiKey'] = params['apiKey']
        d['secretKey']=params['sign']

        # 使用json打包并发送
        j = json.dumps(d)

        # 若触发异常则重连
        try:
            self.rest.send(j)
        except Exception as ex:
            print(u'CCHOKEX.sendTradingRequest exception:{},{}'.format(str(ex), traceback.format_exc()), file=sys.stderr)

    # ----------------------------------------------------------------------
    def login(self):
        """
        登录
        :return:
        """
        params = {}
        params['apikey'] = self.apiKey
        params['sign'] = self.generateSign(params)

        # 生成请求
        d = {}
        d['apiKey'] = params['apiKey']
        d['secretKey']=params['sign']

        # 使用json打包并发送
        j = json.dumps(d)

        # 若触发异常则重连
        try:
            self.rest.send(j)
        except Exception as ex:
            print(u'CCHOKEX.login exception:{},{}'.format(str(ex), traceback.format_exc()), file=sys.stderr)

    # ----------------------------------------------------------------------
    def futureSubscribeIndex(self, symbol):
        """
        订阅期货合约指数行情
        :param symbol: 合约
        :return:
        """
        channel = 'ok_sub_futureusd_%s_index' % symbol
        self.sendTradingRequest(channel, {})

    # ----------------------------------------------------------------------
    def futureAllIndexSymbol(self):
        """
        订阅所有的期货合约指数行情
        :return:
        """
        for symbol in CONTRACT_SYMBOL:
            self.futureSubscribeIndex(symbol)

    # ----------------------------------------------------------------------
    def futureTrade(self, symbol_pair, contractType, type_, price, amount, _match_price='0', _lever_rate=None):
        """期货委托"""
        params = {}
        params['symbol'] = str(symbol_pair)
        params['contractType'] = str(contractType)
        params['price'] = str(price)
        params['amount'] = str(amount)
        params['type'] = type_  # 1:开多 2:开空 3:平多 4:平空
        params['match_price'] = _match_price  # 是否为对手价： 0:不是 1:是 当取值为1时,price无效

        if _lever_rate != None:
            params['lever_rate'] = _lever_rate
        else:
            params['lever_rate'] = str(self.use_lever_rate)

        channel = 'ok_futureusd_trade'

        self.sendTradingRequest(channel, params)

    # ----------------------------------------------------------------------
    def futureCancelOrder(self, symbol_pair, orderid, contract_type):
        """
        期货撤单指令
        :param symbol_pair: 合约对
        :param orderid: 委托单编号
        :param contract_type: 合约类型
        :return:
        """
        params = {}
        params['symbol'] = str(symbol_pair)
        params['order_id'] = str(orderid)
        params['contract_type'] = str(contract_type)

        channel = 'ok_futureusd_cancel_order'

        self.sendTradingRequest(channel, params)

    # ----------------------------------------------------------------------
    def futureUserInfo(self):
        """查询期货账户"""
        channel = 'ok_futureusd_userinfo'
        self.sendTradingRequest(channel, {})

    # ----------------------------------------------------------------------
    def futureSubUserInfo(self):
         channel = 'ok_sub_futureusd_userinfo'
         self.sendTradingRequest(channel, {})

    # ----------------------------------------------------------------------
    def futureOrderInfo(self, symbol_pair, order_id, contractType, status, current_page, page_length=50):
        """
        发出查询期货委托
        :param symbol_pair: 合约对
        :param order_id: 委托单编号
        :param contract_type: 合约类型
        :param status: 状态
        :param current_page:当前页
        :param page_length: 每页长度
        :return:
        """
        params = {}
        params['symbol'] = str(symbol_pair)
        params['order_id'] = str(order_id)
        params['contractType'] = str(contractType)
        params['status'] = str(status)
        params['current_page'] = str(current_page)
        params['page_length'] = str(page_length)

        channel = 'ok_futureusd_orderinfo'

        self.sendTradingRequest(channel, params)

    # ----------------------------------------------------------------------
    def futureAllUnfinishedOrderInfo(self):
        """
        订阅所有未完成的委托单信息
        :return:
        """
        for symbol in CONTRACT_SYMBOL:
            symbol_usd = symbol + "_usd"
            for contract_type in CONTRACT_TYPE:
                # orderid = -1,
                self.futureOrderInfo(symbol_usd, -1, contract_type, 1, 1, 50)

    # ----------------------------------------------------------------------
    def subscribeFutureUserInfo(self):
        """订阅期货账户信息"""
        channel = 'ok_sub_futureusd_userinfo'
        self.future_userinfo()
        self.sendTradingRequest(channel, {})

    # ----------------------------------------------------------------------
    def subscribeFuturePositions(self):
        """订阅期货持仓信息"""
        channel = 'ok_sub_futureusd_positions'

        self.sendTradingRequest(channel, {})

